'''
Created on 2012-3-29上午11:58:32

@author: nagat
@email:  yasenagat@gmail.com
'''

#类的通常组成:函数(方法)，变量(称为类变量),计算出的属性(称为特性)
#属性和变量让我感觉好郁闷,一直以为是一回事的

#所有函数的执行都假定在一个实例调用，这个实例作为方法的第一个参数传递进去！！！要不要吐血了！

#self代表当前的类实例,迷糊吗

#定义类
class Game:
    #变量
    count=0
    #构造方法,只能有一个构造方法
    def __init__(self,name,num):
        #name,num为属性
        self.name = name
        self.num = num
        Game.count += 1
    
    def sayName(self):
        print('游戏名称：',self.name)

print(Game.count) #0
print(Game.count) #0

game1 = Game('dota',10)
print(game1.count) #1
print(Game.count) #1 类变量

game2 = Game('lol',10)
print(game2.count)  #2
print(Game.count) #2 类变量

#看看方法调用一
game1.sayName() # Game.sayName(dota)
#方法调用二,这种方法对于菜鸟来说，确实蛋疼无比~!
Game.sayName(game2)
#现在你知道self是什么吧，是不是感觉有点DT



#类的继承
#好吧，宇宙已经无法组织我打dota了
class Dota(Game):
    
    def __init__(self,name,num,author):
        #显示 调用父类的构造方法,亲，不会自动调用哟！！！！
        Game.__init__(self, name, num)
        self.author = author
        
    #重写父类的方法
    def sayName(self):
        Game.sayName(self)#父类此方法不是必须调用，但一般会调用，否则也没必要重写方法了，另外命名方法就好了，是不是有点窘！
#        super().sayName() #调用父类方法，貌似2不支持，这两个方法神马却别!
        print('作者是',self.author)
dota = Dota('dota',10,'iceforg')

#我们看到数量是3，说明子类调用父类的构造方法成功了！父类中有++
print('游戏数量：',dota.count) #3

dota.sayName()


#python支持多继承
#Davide M.Beazley说作为一般规则，最好避免多继承，好吧

#这里下面是个错误的例子，蛋疼不已
#class Lol(Game):
#    
#    def __init__(self):
#        pass
#   
#   
#lol = Lol()
#lol.sayName()

#多继承略过。。


#所有函数的执行都假定在一个实例调用，这个实例作为方法的第一个参数传递进去！！！要不要吐血了！

#静态方法  类方法

class War3:
    n = 1
    #静态方法
    @staticmethod
    def sayName():
        print('war3')
    
    @classmethod
    def cm(cls,str):
        cls.sayName()
        print(str)
        print(cls.n)
        
    #普通方法
    def nm(self,x,y):
        return x+y
        
#类名调用 静态方法    ,其实实例也可以调用静态方法和类方法   war3 = War3(); war3.sayName()
War3.sayName()

#类方法
War3.cm('不错')

class W(War3):
    n= 2
    
    @staticmethod
    def sayName():
        print('w')

#调用cm方法，相当于把w当作第一参数传递过去,cls=W，cls.sayName()调用的是W的重写的sayName方法  
W.cm('嘿嘿') #War3.cm(W,'')



#挠头的特性来啦

class Hero:
    
    def __init__(self,level):
        self.level = level
        
    @property
    def hp(self):
        return self.level * 19
    
    @property
    def mp(self):
        return self.level * 9
    
    def at(self):
        return self.hp*11
    
#错误的
#print(Hero.mp())
#错误的
#print(Hero.hp())

hero = Hero(25)

#报错
#print(hero.hp())
#print(hero.mp())

#真的是特性，必须特
print('hp的值：',hero.hp)
print('mp的值：',hero.mp)

#方法作为隐式的特性来处理
#不调用方法
#返回方法对象，这是不是个奇迹呢
at = hero.at
print(at)#打印方法对象
ret = at()#调用方法
print('返回值：',ret)


# 知道SKY吗
#装饰器很给力啊
class FootMan:
    
    def __init__(self,name):
        self.__name = name
        
    @property
    def name(self):
        return self.__name
    @name.setter
    def name(self,value):
        if not isinstance(value, str):
            raise TypeError('必须是字符串')

        else:
            self.__name = value
            
    @name.deleter
    def name(self):
        raise TypeError('不允许删除')

foot = FootMan('小A')
#print(foot.__name)
print(foot.name) #调用foot的get方法

#foot.name = 1 #会报错的呀
foot.name = 'a'

#del foot.name #会报错的呢



##描述符略过


#私有属性
class A:
    
    def __init__(self):
        self.__x = 3 #self.__A__x
        
    def __spam(self): #self__A__spam
        print(1)
    
    def bar(self): 
        self.__spam()#A.__spam
        print(self.__x) #在外面没法调用呀
a = A()
#蛋疼的访问不了
#print(a.__x)
a.bar()


#测试类型 isinstance(obj,类型)
print(isinstance(1, int))
print(isinstance('a', str))

class B:
    pass

b = B()
print(isinstance(b, B))


#抽象基类，略过

#元类，略过

#装饰器

#吐槽下，这有些书写的真垃圾

#例如：第1章，讲A，说A用到了B机制，没看懂(悲剧),书上说B机制会在第N章详细讲述，
#然后一直看到N章，讲B机制，说B用到C,D,E,F机制
#囧，有没看懂,书上说C,D,E,F机制会在后面N章讲，我顶你个肺啊





    